package com.leejxx.health.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.leejxx.health.dao.MenuDao;
import com.leejxx.health.dao.RoleDao;
import com.leejxx.health.dao.UserDao;
import com.leejxx.health.entity.PageResult;
import com.leejxx.health.entity.QueryPageBean;
import com.leejxx.health.exception.BusinessRuntimeException;
import com.leejxx.health.pojo.Menu;
import com.leejxx.health.pojo.Role;
import com.leejxx.health.service.MenuService;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author LeeJx
 * @ClassName MenuServiceImpl
 * @Description TODO
 * @date 2021/1/11 11:28
 * @Version 1.0
 */
@DubboService
public class MenuServiceImpl implements MenuService {
    @Autowired
    private MenuDao menuDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private RoleDao roleDao;

    @Override
    public PageResult findByPage(QueryPageBean queryPageBean) {
        PageHelper.startPage(queryPageBean.getCurrentPage(), queryPageBean.getPageSize());
        Page<Menu> page = menuDao.findByCondition(queryPageBean.getQueryString());
        return new PageResult(page.getTotal(), page.getResult());
    }

    @Override
    public List<Menu> findChildMenu() {
        return menuDao.findChildMenu();
    }

    @Override
    @Transactional
    public void addParentMenu(Menu menu, List<Integer> menuIds) {
        if (null == menu.getName()) {
            throw new BusinessRuntimeException("父菜单名称选项不能为空");
        }
        menu.setLevel(1);
        menuDao.addMenu(menu);
        Integer parentId = menuDao.findId(menu.getName());
        if (null != menuIds && menuIds.size() > 0) {
            for (Integer childId : menuIds) {
                menuDao.insertChildMenuId(parentId, childId);
            }
        }
    }

    @Override
    public void addChildMenu(Menu menu) {
        if (null == menu.getName() || null == menu.getLinkUrl()) {
            throw new BusinessRuntimeException("子菜单名称和访问路径不能为空");
        } else {
            menu.setLevel(2);
            menuDao.addMenu(menu);
        }
    }

    @Override
    public Menu findById(Integer menuId) {
        return menuDao.findById(menuId);
    }

    @Override
    public List<Integer> findChildIds(Integer parentId) {
        return menuDao.findChildIds(parentId);
    }

    @Override
    public List<Menu> findAllChildMenu() {
        return menuDao.findAllChildMenu();
    }

    @Override
    @Transactional
    public void editParentMenu(Menu menu, List<Integer> menuIds) {
        if (null == menu.getName()) {
            throw new BusinessRuntimeException("父菜单名称选项不能为空");
        }
        menu.setLevel(1);
        menuDao.editMenu(menu);
        Integer parentId = menuDao.findId(menu.getName());
        if (null != menuIds && menuIds.size() > 0) {
            for (Integer childId : menuIds) {
                menuDao.insertChildMenuId(parentId, childId);
            }
        }
    }

    @Override
    public void editChildMenu(Menu menu) {
        if (null == menu.getName() || null == menu.getLinkUrl()) {
            throw new BusinessRuntimeException("子菜单名称和访问路径不能为空");
        } else {
            menu.setLevel(2);
            menuDao.editMenu(menu);
        }
    }

    @Override
    @Transactional
    public void delete(Integer menuId) {
        Menu menu = menuDao.findById(menuId);
        if (menu.getLevel() == 1) {
            Long count = menuDao.finCountOfChildMenu(menu.getId());
            if (count > 0) {
                throw new BusinessRuntimeException("该父菜单绑定其他子菜单，无法删除");
            } else if (count == 0) {
                menuDao.delete(menuId);
            }
        } else if (menu.getLevel() == 2) {
            menuDao.delete(menuId);
        }
    }

    @Override
    @Transactional
    public List<Map<String, Object>> getMenuList(String username) {
        Integer userId = userDao.findUserId(username);
        List<Role> roles = roleDao.findByUserId(userId);
        //得到该角色下所有的menuId
        List<List<Integer>> menuIds = new ArrayList<>();
        for (Role role : roles) {
            menuIds.add(menuDao.findMenuIdByRoleId(role.getId()));
        }

        //去重合并
        List<Integer> listAllOfMenuIds = new ArrayList<>();
        for (List<Integer> menuId : menuIds) {
            listAllOfMenuIds.addAll(menuId);
        }
        List<Integer> menuIdDistinct = listAllOfMenuIds.stream().distinct().collect(Collectors.toList());

        //获取该角色下的所有菜单信息
        List<Menu> menus = new ArrayList<>();
        for (Integer menuId : menuIdDistinct) {
            menus.add(menuDao.findById(menuId));
        }

        //分离父菜单和子菜单
        List<Menu> parentMenus = new ArrayList<>();
        List<Menu> childMenus = new ArrayList<>();
        for (Menu menu : menus) {
            if (menu.getLevel() == 1) {
                parentMenus.add(menu);
            } else if (menu.getLevel() == 2) {
                childMenus.add(menu);
            }
        }

        List<Map<String, Object>> menuList = new ArrayList<>();

        for (Menu parentMenu : parentMenus) {
            Map<String, Object> menuMap = new LinkedHashMap<>();
            List<Map<String, Object>> childMenuMapList = new ArrayList<>();

            menuMap.put("path", parentMenu.getPath());
            menuMap.put("title", parentMenu.getName());
            menuMap.put("icon", parentMenu.getIcon());

            for (Menu childMenu : childMenus) {
                Map<String, Object> childMenuMap = new LinkedHashMap<>();
                if (childMenu.getParentMenuId().equals(parentMenu.getId())) {
                    childMenuMap.put("path", childMenu.getPath());
                    childMenuMap.put("title", childMenu.getName());
                    childMenuMap.put("linkUrl", childMenu.getLinkUrl());
                }
                childMenuMapList.add(childMenuMap);

                childMenuMapList.removeIf(Map::isEmpty);

                menuMap.put("children", childMenuMapList);
            }
            menuList.add(menuMap);
        }

        return menuList;
    }
}
